package com.ozo.easy.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ozo.easy.common.config.OzoProperties;
import com.ozo.easy.common.model.*;
import com.ozo.easy.common.util.SortUtil;
import com.ozo.easy.common.exception.ServiceException;
import com.ozo.easy.entity.SysDept;
import com.ozo.easy.exception.ServiceExceptionEnum;
import com.ozo.easy.mapper.SysDeptMapper;
import com.ozo.easy.pojo.vo.SysUserDetailVO;
import com.ozo.easy.entity.SysUser;
import com.ozo.easy.mapper.SysUserMapper;
import com.ozo.easy.pojo.dto.SysUserSaveDTO;
import com.ozo.easy.pojo.dto.SysUserQueryDTO;
import com.ozo.easy.pojo.vo.SysUserVO;
import com.ozo.easy.service.ISysUserService;
import com.ozo.easy.pojo.vo.SysDictDataVO;
import com.ozo.easy.service.ISysDictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户 服务实现类
 *
 * @author ozo
 * @version 1.0
 * @date 2025-01-26 16:01:47
 */
@RequiredArgsConstructor
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    private final ISysDictTypeService sysDictTypeService;

    private final SysDeptMapper sysDeptMapper;

    private final OzoProperties ozoProperties;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SysUserSaveDTO saveDTO) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, saveDTO.getUsername());
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new ServiceException(ServiceExceptionEnum.USERNAME_EXISTS);
        }
        if (StrUtil.isNotBlank(saveDTO.getMobile())) {
            LambdaQueryWrapper<SysUser> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(SysUser::getMobile, saveDTO.getMobile());
            Long count1 = baseMapper.selectCount(queryWrapper1);
            if (count1 > 0) {
                throw new ServiceException(ServiceExceptionEnum.MOBILE_EXISTS);
            }
        }

        SysUser sysUser = BeanUtil.copyProperties(saveDTO, SysUser.class);
        baseMapper.insert(sysUser);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(BaseBatchDTO<Long> batchDTO) {
        baseMapper.deleteBatchIds(batchDTO.getIdList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysUserSaveDTO saveDTO) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, saveDTO.getUsername())
                .ne(SysUser::getId, saveDTO.getId());
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new ServiceException(ServiceExceptionEnum.USERNAME_EXISTS);
        }
        if (StrUtil.isNotBlank(saveDTO.getMobile())) {
            LambdaQueryWrapper<SysUser> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(SysUser::getMobile, saveDTO.getMobile())
                    .ne(SysUser::getId, saveDTO.getId());
            Long count1 = baseMapper.selectCount(queryWrapper1);
            if (count1 > 0) {
                throw new ServiceException(ServiceExceptionEnum.MOBILE_EXISTS);
            }
        }

        SysUser sysUser = BeanUtil.copyProperties(saveDTO, SysUser.class);
        baseMapper.updateById(sysUser);
    }

    @Override
    public PageResult<SysUserVO> page(BasePage basePage, SysUserQueryDTO queryDTO) {
        Integer pageNum = basePage.getPageNum();
        Integer pageSize = basePage.getPageSize();

        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        // 排序
        String order = queryDTO.getOrder();
        if (StrUtil.isBlank(order)) {
            queryWrapper.lambda().orderByDesc(SysUser::getId);
        } else {
            SortUtil.setSortCondition(queryWrapper, queryDTO.getProp(), order);
        }
        // 条件
        queryWrapper.lambda()
                .eq(Objects.nonNull(queryDTO.getDeptId()), SysUser::getDeptId, queryDTO.getDeptId())
                .like(StrUtil.isNotBlank(queryDTO.getUsername()), SysUser::getUsername, queryDTO.getUsername())
                .like(StrUtil.isNotBlank(queryDTO.getNickname()), SysUser::getNickname, queryDTO.getNickname());
        Page<SysUser> page = baseMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);

        PageResult<SysUserVO> pageResult = new PageResult<>();
        pageResult.setPageNum(pageNum);
        pageResult.setPageSize(pageSize);
        pageResult.setPage(page.getPages());
        pageResult.setTotal(page.getTotal());
        List<SysUser> recordList = page.getRecords();

        List<SysUserVO> recordVOList = BeanUtil.copyToList(recordList, SysUserVO.class);

        if (CollUtil.isNotEmpty(recordVOList)) {
            Map<String, String> genderMap = sysDictTypeService.listData("GENDER").stream().collect(Collectors.toMap(SysDictDataVO::getDictValue, SysDictDataVO::getDictItem));

            Set<Long> deptIds = recordVOList.stream().map(SysUserVO::getDeptId).collect(Collectors.toSet());
            Map<Long, String> deptMap = sysDeptMapper.selectBatchIds(deptIds).stream().collect(Collectors.toMap(SysDept::getId, SysDept::getDeptName));

            for (SysUserVO sysUserVO : recordVOList) {
                sysUserVO.setGenderDesc(genderMap.get(sysUserVO.getGender()));
                sysUserVO.setDeptName(deptMap.get(sysUserVO.getDeptId()));
            }
        }

        pageResult.setResults(recordVOList);
        return pageResult;
    }

    @Override
    public SysUserDetailVO detail(Long id) {
        SysUser sysUser = baseMapper.selectById(id);
        if (Objects.isNull(sysUser)) {
            throw new ServiceException(ServiceExceptionEnum.DATA_NOT_EXISTS);
        }
        SysUserDetailVO sysUserDetailVO = BeanUtil.copyProperties(sysUser, SysUserDetailVO.class);
        Long deptId = sysUser.getDeptId();
        if (Objects.nonNull(deptId)) {
            SysDept sysDept = sysDeptMapper.selectById(deptId);
            sysUserDetailVO.setDeptName(sysDept != null ? sysDept.getDeptName() : "");
        }
        return sysUserDetailVO;
    }

    @Override
    public SysUser getByUsername(String username) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, username);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public void resetPwd(Long id) {
        LambdaUpdateWrapper<SysUser> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SysUser::getId, id)
                .set(SysUser::getPassword, SecureUtil.md5(ozoProperties.getPassword()));
        baseMapper.update(updateWrapper);
    }

}
